package com.hulizuofang.wol.channel.client;

import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.HasCloseHandlers;
import com.google.gwt.event.logical.shared.HasOpenHandlers;
import com.google.gwt.event.logical.shared.OpenEvent;
import com.google.gwt.event.logical.shared.OpenHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.inject.Inject;

public class ChannelConnector implements HasOpenHandlers<Void> , HasCloseHandlers<Void>, HasChannelErrorHandlers, HasChannelMessageHandlers {

	private final EventBus eventBus;

	@Inject
	public ChannelConnector(EventBus eventBus) {
		this.eventBus = eventBus;
	}
	
	public native void addChannel(String token) /*-{
		try {
			if (typeof console != 'undefined') {
				var logger=console;
			} else {
				var logger = {log:function(){},error:function(){}};
			}
			logger.log("starting init goog.appengine.Channel for token"+token);
	    	var channel = new $wnd.goog.appengine.Channel(token);
	    	
			logger.log("starting bind javascript handler to ChannelConnector");
			
			var that = this;
			
	    	var fireOpenEvent = function() {that.@com.hulizuofang.wol.channel.client.ChannelConnector::fireOpenEvent()();}
	    	var fireChannelMessageEvent =
	    		function(evt) {
	    			try {
		    			logger.log("ready to fire type:"+(typeof evt.data)+", value:"+evt.data);
	    				that.@com.hulizuofang.wol.channel.client.ChannelConnector::fireChannelMessageEvent(Ljava/lang/String;)(evt.data);
	    			} catch (e) {
				    	logger.error("Unexpected Javascript Error: %o",e);
				    	throw e;
	    			}
	    		}
	    	var fireCloseEvent = function() {that.@com.hulizuofang.wol.channel.client.ChannelConnector::fireCloseEvent()();}
	    	var fireErrorEvent = function(s) {that.@com.hulizuofang.wol.channel.client.ChannelConnector::fireErrorEvent(Ljava/lang/String;)(s);}
	    	
	    	var handler = {
	          'onopen': fireOpenEvent,
	          'onmessage': fireChannelMessageEvent,
	          'onerror': fireErrorEvent,
	          'onclose': fireCloseEvent
	        };
	        
			if (typeof console != 'undefined') console.log("starting openning channel");
	        var socket = channel.open(handler);
			if (typeof console != 'undefined') console.log("starting assign onopen on socket");
	        socket.onopen = fireOpenEvent;
			if (typeof console != 'undefined') console.log("starting assign onmessage on socket");
	        socket.onmessage = fireChannelMessageEvent;
			if (typeof console != 'undefined') console.log("finishing init goog.appengine.Channel for token"+token);
		} catch (e) {
	    	if (typeof console != 'undefined') console.error("Unexpected Javascript Error: %o",e);
	    	throw e;
		}
    }-*/;

	protected void fireOpenEvent() {
		fireEvent(new MyOpenEvent());
	}
	
	protected void fireCloseEvent() {
		fireEvent(new MyCloseEvent());
	}
	
	protected void fireChannelMessageEvent(String data) {
		fireEvent(new ChannelMessageEvent(data));
	}
	
	protected void fireErrorEvent(String s) {
		fireEvent(new ChannelErrorEvent(s));
	}
	
	@Override
	public void fireEvent(GwtEvent<?> event) {
		eventBus.fireEvent(event);
	}

	@Override
	public HandlerRegistration addChannelMessageHandler(ChannelMessageHandler handler) {
		return eventBus.addHandler(ChannelMessageEvent.getType(), handler);
	}
	
	@Override
	public HandlerRegistration addChannelErrorHandler(ChannelErrorHandler handler) {
		return eventBus.addHandler(ChannelErrorEvent.getType(), handler);
	}

	@Override
	public HandlerRegistration addCloseHandler(CloseHandler<Void> handler) {
		return eventBus.addHandler(CloseEvent.getType(), handler);
	}

	@Override
	public HandlerRegistration addOpenHandler(OpenHandler<Void> handler) {
		return eventBus.addHandler(OpenEvent.getType(), handler);
	}
}
